package com.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.*;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.entity.GoodsVo;
import com.es.param.EsAggsParam;
import com.es.param.EsSearchPageParam;
import com.es.param.EsSearchParam;
import com.es.vo.EsRestBulkDocVo;
import com.es.EsRestClientUtil;
import com.es.param.EsRestDocParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * xxx
 *
 * @author heyonghao
 * @date 2023/2/3
 */
@RestController
@RequestMapping("/esDoc")
public class EsDocController {

    @Autowired
    private EsRestClientUtil esRestClientUtil;


    @PostMapping("/add")
    public String esclienAdd(String indexName, @RequestBody GoodsVo goodsVo) {
        return esRestClientUtil.addDoc(indexName, String.valueOf(IdUtil.getSnowflakeNextId()),goodsVo);
    }

    @PostMapping("/edit")
    public String esclienEit(String indexName,String id ,@RequestBody GoodsVo goodsVo) {
        return esRestClientUtil.editDocById(indexName,id,goodsVo,GoodsVo.class);
    }

    @PostMapping("/addBatch")
    public Long addBatch(String indexName, @RequestBody List<EsRestBulkDocVo> esRestBulkDocVos) {
        return esRestClientUtil.addBatchDoc(indexName, esRestBulkDocVos);
    }

    /**
     * 批量添加性能测试 100w数据
     * @param indexName 索引
     * @return api took
     */
    @GetMapping("/addBatchTest")
    public Long addBatch(String indexName) {
        List<EsRestBulkDocVo> esRestBulkDocVos = new LinkedList<>();
        System.out.println("封装10w数据开始"+DateUtil.now());
        for (int i = 0; i < 10_0000; i++) {
            EsRestBulkDocVo esRestBulkDocVo = new EsRestBulkDocVo();
            GoodsVo goodsVo = new GoodsVo();
            goodsVo.setGoodsName("商品"+i);
            goodsVo.setStock(i);
            goodsVo.setPrice((double) i);
            esRestBulkDocVo.setIndexName(indexName);
            esRestBulkDocVo.setDoc(goodsVo);
            esRestBulkDocVos.add(esRestBulkDocVo);
        }
        System.out.println("封装结束"+DateUtil.now());
        System.out.println("开始执行添加到es"+DateUtil.now());
        Long took = esRestClientUtil.addBatchDoc(indexName, esRestBulkDocVos);
        System.out.println("执行结束"+DateUtil.now());
        return took;
    }

    @GetMapping("/getDocById")
    public String getDocById(EsRestDocParam<GoodsVo> param){
        param.setDocClass(GoodsVo.class);
        GoodsVo doc = esRestClientUtil.getDocById(param);
        return doc.toString();
    }

    @GetMapping("/listMatchOne")
    public Object listMatchOne(EsSearchParam<GoodsVo> param){
        param.setTargetClass(GoodsVo.class);
        param.setSortFiled("inStockTime");
        param.setSortOrder(SortOrder.Desc);
        List<Hit<GoodsVo>> hits = esRestClientUtil.listMatchOne(param);
        List<GoodsVo> list = hits.stream().map(Hit::source).collect(Collectors.toList());
        return list;
    }

    @GetMapping("/listMatchPage")
    public Object listMatchPage(EsSearchPageParam<GoodsVo> param){
        param.setTargetClass(GoodsVo.class);
        param.setSortFiled("inStockTime");
        param.setSortOrder(SortOrder.Desc);
        param.setTargetClass(GoodsVo.class);
        List<Hit<GoodsVo>> hits = esRestClientUtil.listMatchPage(param);
        List<GoodsVo> list = hits.stream().map(Hit::source).collect(Collectors.toList());
        return list;
    }

    @GetMapping("/listHlight")
    public Object listHlight(EsSearchParam<GoodsVo> param){
        param.setTargetClass(GoodsVo.class);
        param.setHlightFiled("goodsName");
        param.setSortFiled("inStockTime");
        param.setSortOrder(SortOrder.Desc);
        List<Hit<GoodsVo>> hits = esRestClientUtil.listHighlight(param);
        Map<String,Object> res= new HashMap<>();
        hits.forEach(e->{
            GoodsVo source = e.source();
            res.put("source",source);
            Map<String, List<String>> highlight = e.highlight();
            res.put("highlight",highlight);
        });
        return res;
    }

    @GetMapping("/groupCount")
    public Object groupCount(EsAggsParam param){
        param.setTargetClass(GoodsVo.class);
        param.setGroupFiled("tags");
        param.setGroupName("tags_group_count");
        Map<String, Aggregate> aggs = esRestClientUtil.aggsByFiled(param);
        List<StringTermsBucket> res = new LinkedList<>();
        aggs.forEach((k,v)->{
            StringTermsAggregate sterms = v.sterms();
            Buckets<StringTermsBucket> buckets = sterms.buckets();
            List<StringTermsBucket> array = buckets.array();
            res.addAll(array);
        });
        return res.toString();
    }

}
